import './index.css'
import * as THREE from 'three'
import {
    GLTFLoader
} from 'three/examples/jsm/Addons.js'
import {
    OrbitControls
} from 'three/examples/jsm/controls/OrbitControls'

import {
    EffectComposer
} from 'three/examples/jsm/Addons.js'
import {
    RenderPass
} from 'three/examples/jsm/Addons.js'
import {
    DotScreenPass
} from 'three/examples/jsm/postprocessing/DotScreenPass.js'
import {
    GlitchPass
} from 'three/examples/jsm/postprocessing/GlitchPass.js'

import {
    ShaderPass
} from 'three/examples/jsm/Addons.js'
import {
    RGBShiftShader
} from 'three/examples/jsm/shaders/RGBShiftShader.js'
import {
    GammaCorrectionShader
} from 'three/examples/jsm/shaders/GammaCorrectionShader.js'

import {
    SMAAPass
} from 'three/examples/jsm/Addons.js'

import {
    UnrealBloomPass
} from 'three/examples/jsm/Addons.js'



/**
 * Size
 */
const Size = {
    width: window.innerWidth,
    height: window.innerHeight
}


/**
 * Camera
 */
const camera = new THREE.PerspectiveCamera(75, Size.width / Size.height, 0.1, 100)
camera.position.set(10, 15, 10)

/**
 * Scene
 */
const scene = new THREE.Scene()

/**
 * Light
 */
const ambientLight = new THREE.AmbientLight(new THREE.Color('#ffffff'), 3)
scene.add(ambientLight)

// const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
// directionalLight.position.set(1, 1, 1);
// scene.add(directionalLight);

// const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);
// directionalLight2.position.set(-1, -1, -1);
// scene.add(directionalLight2);

// const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.8);
// directionalLight3.position.set(-1, 1, -1);
// scene.add(directionalLight3);

// const directionalLight4 = new THREE.DirectionalLight(0xffffff, 0.8);
// directionalLight4.position.set(1, -1, 1);
// scene.add(directionalLight4);


// const spotLight = new THREE.SpotLight(0xffffff, 3, 15, Math.PI * 0.1, 0.25, 1)
// spotLight.position.set(0, 10, 0)
// scene.add(spotLight)
// // const spotLightHelper = new THREE.SpotLightHelper(spotLight)
// scene.add(spotLightHelper)




/**
 * Model
 */
const loader = new GLTFLoader();

loader.load('../assets/models/su7/scene.gltf',
    function (gltf) {
        console.log('success')
        gltf.scene.scale.set(5, 5, 5)
        gltf.scene.castShadow = true
        scene.add(gltf.scene)
        updateAllMaterials()
    },
    function (progress) {
        console.log('progress')
    },
    function (error) {
        console.log('error')
        console.log(error)
    },
)





/**
 * Renderer
 */
const canvas = document.querySelector('canvas.webgl')
const renderer = new THREE.WebGLRenderer({
    canvas,
    antialias: true,
})
renderer.setSize(Size.width, Size.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.setClearColor(0x000000, 1)
// 物理上正确的光照模式
renderer.physicallyCorrectLights = true
// outputEncoding 渲染器的输出编码
renderer.outputEncoding = THREE.sRGBEncoding
//toneMappingExposure 色调映射的曝光级别
renderer.toneMappingExposure = 2.5
// shadow
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap


/**
 * Post  processing
 */
//Render target
console.log(renderer.getPixelRatio())
const renderTarget = new THREE.WebGLRenderTarget(800, 600, {
    samples: renderer.getPixelRatio() === 1 ? 2 : 0
})


const effectComposer = new EffectComposer(renderer, renderTarget);
effectComposer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
effectComposer.setSize(Size.width, Size.height)

const renderPass = new RenderPass(scene, camera)
effectComposer.addPass(renderPass)

// 灰白点效果
const dotScreenPass = new DotScreenPass()
dotScreenPass.enabled = false
effectComposer.addPass(dotScreenPass)

// 故障效果
const glitchPass = new GlitchPass()
glitchPass.enabled = false
effectComposer.addPass(glitchPass)

// 颜色偏移效果
const rgbShaderPass = new ShaderPass(RGBShiftShader)
rgbShaderPass.enabled = false
effectComposer.addPass(rgbShaderPass)
// 亮度校正
const gammaCorrectPass = new ShaderPass(GammaCorrectionShader)
gammaCorrectPass.enabled = true
effectComposer.addPass(gammaCorrectPass)

// 泛光效果
const unrealBloomPass = new UnrealBloomPass()
unrealBloomPass.enabled = false
unrealBloomPass.strength = 0.3 //泛光强度（默认 1，控制光晕扩散程度）。
unrealBloomPass.radius = 1 //最大模糊半径（默认 1，单位为像素）
unrealBloomPass.threshold = 0.6 //泛光触发阈值（默认 0.85，仅处理高亮区域）
effectComposer.addPass(unrealBloomPass)

// Tint Pass
const TintShader = {
    uniforms: {
        tDiffuse: {
            value: null
        }
    },
    vertexShader: `
        varying vec2 vUv;
        void main(){
           gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
           vUv = uv;
        }
    `,
    fragmentShader: `
        uniform sampler2D tDiffuse;
        varying vec2 vUv;
        void main(){
           vec4 color = texture2D(tDiffuse,vUv);
           color.r += 0.1;
           gl_FragColor = color;
        }
    `
}
const tintPass = new ShaderPass(TintShader)
tintPass.enabled = false
effectComposer.addPass(tintPass)


//Displacement Pass
const DisplacementShader = {
    uniforms: {
        tDiffuse: {
            value: null
        },
        uTime:{
            value:null
        }
    },
    vertexShader: `
        varying vec2 vUv;
        void main(){
           gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
           vUv = uv;
        }
    `,
    fragmentShader: `
        uniform sampler2D tDiffuse;
        uniform float uTime; 

        varying vec2 vUv;

        void main(){
           vec2 newUv = vec2(
              vUv.x,
              vUv.y + sin(vUv.x  *  10.0 + uTime) *  0.1
           );
           vec4 color = texture2D(tDiffuse,newUv);
           gl_FragColor = color;
        }
    `
}
const displacementPass = new ShaderPass(DisplacementShader)
displacementPass.material.uniforms.uTime.value = 0
effectComposer.addPass(displacementPass)


// smaapass 抗锯齿处理通道 放在最后
if (renderer.getPixelRatio() === 1 && !renderer.capabilities.isWebGL2) {
    const smaaPass = new SMAAPass()
    effectComposer.addPass(smaaPass)
}



/**
 * Environment map
 */
const cubeTextureLoader = new THREE.CubeTextureLoader()
const environmentMap = cubeTextureLoader.load([
    '../assets/textures/environmentMaps/0/px.jpg',
    '../assets/textures/environmentMaps/0/nx.jpg',
    '../assets/textures/environmentMaps/0/py.jpg',
    '../assets/textures/environmentMaps/0/ny.jpg',
    '../assets/textures/environmentMaps/0/pz.jpg',
    '../assets/textures/environmentMaps/0/nz.jpg',
])
environmentMap.encoding = THREE.sRGBEncoding
scene.background = environmentMap


/**
 * 优化材质
 */
const updateAllMaterials = () => {
    scene.traverse((child) => {
        if (child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial) {
            // console.log(child)
            //遍历模型中的 Mesh，并添加材质的环境贴图，将环境贴图强度设置为 2.5
            child.material.envMap = environmentMap
            child.material.envMapIntensity = 2.5
            // 开启阴影
            child.castShadow = true
            child.receiveShadow = true
        }
    })
}


/**
 * OrbitControls
 */
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true


/**
 * Update
 */
const clock = new THREE.Clock()
const tick = () => {
    const elpasedTime = clock.getElapsedTime()

    // Update Pass
    displacementPass.material.uniforms.uTime.value = elpasedTime

    controls.update();
    // renderer.render(scene, camera)
    effectComposer.render()
    requestAnimationFrame(tick)
}
tick()


/**
 * resize
 */
window.addEventListener('resize', () => {
    Size.width = window.innerWidth
    Size.height = window.innerHeight

    camera.aspect = Size.width / Size.height
    camera.updateProjectionMatrix()

    renderer.setSize(Size.width, Size.height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))


    //update effect compliser
    effectComposer.setSize(Size.width, Size.height)
    effectComposer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})